package com.itwxz.system.service.impl;


import cn.hutool.core.util.DesensitizedUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itwxz.common.config.WxzConfig;
import com.itwxz.common.config.YiLaoConfig;
import com.itwxz.common.constant.EmoticonConstants;
import com.itwxz.common.core.domain.R;
import com.itwxz.common.core.domain.entity.SysUser;
import com.itwxz.common.exception.ServiceException;
import com.itwxz.common.utils.SecurityUtils;
import com.itwxz.common.utils.bean.BeanUtils;
import com.itwxz.system.domain.dto.CreateWxzOrderDto;
import com.itwxz.system.domain.dto.SelectOrderDto;
import com.itwxz.system.domain.po.WxzOrder;
import com.itwxz.system.domain.po.YiLaoForm;
import com.itwxz.system.domain.vo.OperateOrderListVo;
import com.itwxz.system.domain.vo.SearchOrderVo;
import com.itwxz.system.domain.vo.StaffRankingVo;
import com.itwxz.system.enums.order.OrderIdentity;
import com.itwxz.system.enums.order.OrderStatus;
import com.itwxz.system.mapper.WxzOrderMapper;
import com.itwxz.system.service.IWxzOrderHistoryService;
import com.itwxz.system.service.IWxzOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 维修站订单Service业务层处理
 *
 * @author gastronome
 * @date 2025-04-05
 */
@Service
@Slf4j
@Transactional
@RequiredArgsConstructor
public class WxzOrderServiceImpl extends ServiceImpl<WxzOrderMapper, WxzOrder> implements IWxzOrderService {
    private final WxzOrderMapper orderMapper;
    private final IWxzOrderHistoryService orderHistoryService;
    private final YiLaoConfig yl;
    private final WxzConfig itWxzConfig;

    // ============================ 查询方法 ============================

    /**
     * 查询维修站订单列表
     *
     * @param wxzOrder 维修站订单查询条件
     * @return 维修站订单列表
     */
    @Override
    public List<SelectOrderDto> selectWxzOrderList(SelectOrderDto wxzOrder) {
        List<SelectOrderDto> selectOrderDtos = orderMapper.selectWxzOrderList(wxzOrder);

        if (!SecurityUtils.hasRole("club_leader"))
            selectOrderDtos.forEach(dto -> dto.setPhone(DesensitizedUtil.mobilePhone(dto.getPhone())));

        return selectOrderDtos;
    }

    /**
     * 查询义劳表数据
     *
     * @param wxzOrder 订单日期范围
     * @return 义劳表数据列表
     */
    @Override
    public List<YiLaoForm> getYiLaoList(SelectOrderDto wxzOrder) {
        // 参数校验：时间区间不能为空
        if (wxzOrder.getCompletionTimeRange() == null || wxzOrder.getCompletionTimeRange().isEmpty())
            throw new ServiceException("请选择时间区间后尝试！" + EmoticonConstants.FLY);

        if (wxzOrder.getCompletionTimeRange().get(0).isAfter(LocalDateTime.now()))
            throw new ServiceException("日期区间内无订单！" + EmoticonConstants.FLY);

        // 查询符合条件的订单列表
        List<YiLaoForm> records = orderMapper.getOrderCountByCompletionTime(wxzOrder);
        if (records.isEmpty())
            throw new ServiceException("日期区间内无订单！" + EmoticonConstants.FLY);

        List<YiLaoForm> list = new ArrayList<>();

        // 获取开始日期
        LocalDateTime day = wxzOrder.getCompletionTimeRange().get(0);

        // 遍历每一条记录
        for (YiLaoForm record : records) {
            int orderCount = record.getOrderCount();

            // 计算并设置订单日期
            for (int i = 0; i < orderCount; i++) {
                // 通过加天数来推算义务劳动日期
                LocalDateTime temp = day.plusDays(i / 2);

                // 深度复制对象，避免引用共享问题
                YiLaoForm recordCopy = BeanUtils.copyBean(record, YiLaoForm.class);
                recordCopy.setDateTime(temp);
                recordCopy.setDepartment(yl.getDepartment());
                recordCopy.setLaborContent(yl.getLaborContent());
                recordCopy.setDepartmentUsed(yl.getDepartmentUsed());
                recordCopy.setMentor(yl.getMentor());
                recordCopy.setLaborHours(yl.getLaborHours());
                recordCopy.setQualityScore(yl.getQualityScore());
                list.add(recordCopy);
            }
        }

        return list;
    }

    /**
     * 查询订单统计数据（按类型分组）
     *
     * @return 订单统计列表
     */
    @Override
    @Cacheable(value = "order-statistics", key = "'type'")
    public List<Map<String, Object>> orderStatistics() {
        QueryWrapper<WxzOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("type", "COUNT(*) AS order_count")
                .groupBy("type")
                .orderByAsc("type");
        return orderMapper.selectMaps(queryWrapper);
    }

    /**
     * 查询当前用户的进行中订单
     *
     * @param userId 用户ID
     * @return 进行中订单列表
     */
    @Override
    @Cacheable(value = "in-progress", key = "#userId")
    public List<WxzOrder> getInProgressListByMe(Long userId) {
        log.info("查询用户{}的进行中订单", userId);
        LambdaQueryWrapper<WxzOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(WxzOrder::getStatus, OrderStatus.IN_PROGRESS.getCode(), OrderStatus.ACCEPT.getCode())
                .eq(WxzOrder::getStaffId, userId);
        return list(queryWrapper);
    }

    /**
     * 查询可操作订单列表
     *
     * @return 可操作订单视图对象
     */
    @Override
    @Cacheable(value = "operate-order", key = "'list'")
    public OperateOrderListVo getOperateList() {
        OperateOrderListVo listVo = new OperateOrderListVo();
        listVo.setPendingList(orderMapper.selectPendingOrder());
        listVo.setInProgressList(orderMapper.selectInProgressOrder());
        return listVo;
    }

    /**
     * 按楼栋查询订单数量
     *
     * @return 楼栋订单统计列表
     */
    @Override
    @Cacheable(value = "order-statistics", key = "'building'")
    public List<Map<String, Object>> getOrderCountByBuilding() {
        return orderMapper.countOrdersByBuilding();
    }

    /**
     * 查询最近7天订单数量
     *
     * @return 最近7天订单统计列表
     */
    @Override
    @Cacheable(value = "order-statistics", key = "'recent7days'", unless = "#result == null || #result.isEmpty()")
    public List<Map<String, Object>> selectRecent7DaysOrderCount() {
        return orderMapper.selectRecent7DaysOrderCount();
    }

    /**
     * 搜索订单
     *
     * @param keyword 关键词（学号、姓名、手机号）
     * @return 订单列表
     */
    @Override
    @Cacheable(value = "order-search", key = "#keyword", unless = "#result == null || #result.isEmpty()")
    public List<SearchOrderVo> searchOrder(String keyword) {
        List<SearchOrderVo> currentOrders = new ArrayList<>();
        List<SearchOrderVo> orders = BeanUtils.copyBeanList(orderMapper.searchOrderWithStaff(keyword), SearchOrderVo.class);
        List<SearchOrderVo> historyOrders = BeanUtils.copyBeanList(orderHistoryService.searchOrderWithStaff(keyword), SearchOrderVo.class);
        currentOrders.addAll(orders);
        currentOrders.addAll(historyOrders);
        return currentOrders;
    }

    /**
     * 查询员工排名
     *
     * @return 员工排名列表
     */
    @Override
    @Cacheable(value = "staff", key = "'ranking'")
    public List<StaffRankingVo> getRanking() {
        // 1️⃣ 获取原始每周记录列表
        List<StaffRankingVo> list = orderMapper.getStaffWeeklyRanking();

        if (list == null || list.isEmpty()) return Collections.emptyList();

        // 2️⃣ 按 staffId 聚合累加 total 和 points
        Map<String, StaffRankingVo> aggregatedMap = list.stream()
                .collect(Collectors.toMap(
                        StaffRankingVo::getStaffId,
                        vo -> StaffRankingVo.builder()
                                .staffId(vo.getStaffId())
                                .nickName(vo.getNickName())
                                .total(vo.getTotal())
                                .points(vo.getPoints())
                                .build(),
                        (v1, v2) -> {
                            v1.setTotal(v1.getTotal() + v2.getTotal());
                            v1.setPoints(v1.getPoints() + v2.getPoints());
                            return v1;
                        }
                ));

        // 3️⃣ 定义额外积分档次（可维护）
        long[] thresholds = {15, 35, 55, 75, 95};
        long[] extraScores = {2, 3, 4, 5, 8};

        return aggregatedMap.values().stream()
                .peek(vo -> {
                    long total = vo.getTotal();
                    for (int i = thresholds.length - 1; i >= 0; i--) {
                        if (total >= thresholds[i]) {
                            vo.setPoints(vo.getPoints() + extraScores[i]);
                            break;
                        }
                    }
                })
                // 5️⃣ 按总积分降序排序
                .sorted(Comparator.comparing(StaffRankingVo::getPoints).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 查询状态为2和3的订单
     *
     * @return 订单列表
     */
    @Override
    @Cacheable(value = "order-status", key = "'23'")
    public List<SearchOrderVo> selectOrderStatus23() {
        return orderMapper.selectOrderStatus23();
    }

    // ============================ 新增方法 ============================

    /**
     * 新增维修站订单
     *
     * @param order 订单信息
     * @return 操作结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "operate-order", key = "'list'"),
            @CacheEvict(value = "order-statistics", allEntries = true),
            @CacheEvict(value = "order-search", allEntries = true),
            @CacheEvict(value = "order-status", allEntries = true)
    })
    public R<String> createWxzOrder(CreateWxzOrderDto order) {
        // 查询该学生是否存在未完成的订单
        LambdaQueryWrapper<WxzOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WxzOrder::getStudentId, order.getStudentId());
        queryWrapper.eq(WxzOrder::getName, order.getName());
        queryWrapper.lt(WxzOrder::getStatus, OrderStatus.COMPLETED.getCode());

        WxzOrder one = getOne(queryWrapper, false);

        // 存在未完成的订单，进行状态判断并返回提示信息
        if (one != null) {
            Integer status = one.getStatus();
            if (Objects.equals(status, OrderStatus.ACCEPT.getCode())) {
                return R.fail("你的订单尚未完成，可以和维修员继续联系哦！");
            } else if (Objects.equals(status, OrderStatus.PENDING.getCode())) {
                return R.fail("你已有报修订单，请等待维修人员与你联系哦！");
            }
        }

        // 没有未完成订单，允许提交新订单
        WxzOrder wxzOrder = com.itwxz.common.utils.bean.BeanUtils.copyBean(order, WxzOrder.class);
        wxzOrder.setStatus(OrderStatus.PENDING.getCode());

        // 老师id要自动填充点东西
        if (Objects.equals(wxzOrder.getIdentity(), OrderIdentity.TEACHER.getCode())) {
            wxzOrder.setStudentId(itWxzConfig.getTeacherId());
            wxzOrder.setBuilding(itWxzConfig.getBuilding());
        }
        log.info(String.valueOf(Objects.equals(wxzOrder.getIdentity(), OrderIdentity.TEACHER.getCode())));
        log.info(wxzOrder.toString());
        save(wxzOrder);

        return R.ok("报修订单提交成功！");
    }

    // ============================ 修改方法 ============================

    /**
     * 接单并更新订单状态
     *
     * @param orderId 订单ID
     * @param userId 用户ID
     * @return 操作结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "operate-order", key = "'list'"),
            @CacheEvict(value = "in-progress", key = "#userId"),
            @CacheEvict(value = "order-statistics", allEntries = true),
            @CacheEvict(value = "order-search", allEntries = true),
            @CacheEvict(value = "order-status", allEntries = true)
    })
    public R<String> accepAndUpdateOrder(String orderId, Long userId) {
        WxzOrder o = getById(orderId);
        if (!Objects.equals(o.getStatus(), OrderStatus.PENDING.getCode()))
            return R.fail("已有人接单，手慢了哦！");

        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (user.getEmail() == null || user.getPhonenumber() == null || user.getPoliticalStatus() == null)
            return R.fail("信息不全，请去个人页完善");

        o.setStatus(OrderStatus.ACCEPT.getCode());
        o.setStaffId(SecurityUtils.getUserId());
        updateById(o);

        return R.ok("接单成功！");
    }

    /**
     * 完成订单
     *
     * @param orderId 订单ID
     * @param userId 用户ID
     * @return 操作结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "operate-order", key = "'list'"),
            @CacheEvict(value = "in-progress", key = "#userId"),
            @CacheEvict(value = "order-statistics", allEntries = true),
            @CacheEvict(value = "order-search", allEntries = true),
            @CacheEvict(value = "order-status", allEntries = true)
    })
    public R<String> completeOrderById(Long orderId, Long userId) {
        WxzOrder order = getById(orderId);
        if (order == null)
            return R.fail("订单不存在");

        if (!(Objects.equals(order.getStatus(), OrderStatus.ACCEPT.getCode()) ||
                Objects.equals(order.getStatus(), OrderStatus.IN_PROGRESS.getCode())))
            return R.fail("只有已接单的订单才能完成");

        order.setStatus(OrderStatus.COMPLETED.getCode());
        order.setCompletionTime(LocalDateTime.now());

        boolean updated = updateById(order);
        return updated ? R.ok("订单已完成") : R.fail("订单完成失败");
    }

    /**
     * 转单操作
     *
     * @param orderId 订单ID
     * @param userId 用户ID
     * @return 操作结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "operate-order", key = "'list'"),
            @CacheEvict(value = "in-progress", key = "#userId"),
            @CacheEvict(value = "order-statistics", allEntries = true),
            @CacheEvict(value = "order-search", allEntries = true),
            @CacheEvict(value = "order-status", allEntries = true)
    })
    public R<String> transferOrder(Long orderId, Long userId) {
        WxzOrder order = getById(orderId);
        if (order == null) {
            return R.fail("订单不存在");
        }

        if (order.getAssignorId() != null) {
            return R.fail("订单不能二次转让，请联系管理员进行操作！");
        }

        if (!Objects.equals(order.getStaffId(), SecurityUtils.getUserId())) {
            return R.fail("用户不匹配！");
        }

        boolean updated = update(new LambdaUpdateWrapper<WxzOrder>()
                .eq(WxzOrder::getId, orderId)
                .set(WxzOrder::getStaffId, null)
                .set(WxzOrder::getAssignorId, order.getStaffId())
                .set(WxzOrder::getStatus, OrderStatus.PENDING.getCode())
        );

        return updated ? R.ok("订单已成功转让") : R.fail("订单转让失败");
    }

    /**
     * 检查并更新订单信息
     *
     * @param wxzOrder 订单信息
     * @return 是否更新成功
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "operate-order", key = "'list'"),
            @CacheEvict(value = "in-progress", key = "#wxzOrder.staffId"),
            @CacheEvict(value = "order-statistics", allEntries = true),
            @CacheEvict(value = "order-search", allEntries = true),
            @CacheEvict(value = "order-status", allEntries = true)
    })
    public boolean checkAndUpdateById(WxzOrder wxzOrder) {
        WxzOrder origin = getById(wxzOrder.getId());
        //订单如果是"待接单"不能更改成"已完成"
        if (Objects.equals(origin.getStatus(), OrderStatus.PENDING.getCode()) &&
                Objects.equals(wxzOrder.getStatus(), OrderStatus.COMPLETED.getCode())) {
            throw new ServiceException("无人接单不可完成！" + EmoticonConstants.DONT);
        }
        if (Objects.equals(origin.getStatus(), OrderStatus.COMPLETED.getCode()) &&
                Objects.equals(wxzOrder.getStatus(), OrderStatus.PENDING.getCode())) {
            throw new ServiceException("订单已完成，不可恢复待接单！" + EmoticonConstants.DONT);
        }

        if (Objects.equals(wxzOrder.getStatus(), OrderStatus.PENDING.getCode()) &&
                wxzOrder.getStatus() < OrderStatus.COMPLETED.getCode())
            wxzOrder.setAssignorId(SecurityUtils.getUserId());

        return updateById(wxzOrder);
    }

    // ============================ 删除方法 ============================

    /**
     * 作废订单（批量）
     *
     * @param ids 订单ID数组
     * @return 是否操作成功
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "operate-order", key = "'list'"),
            @CacheEvict(value = "in-progress", allEntries = true),
            @CacheEvict(value = "order-statistics", allEntries = true),
            @CacheEvict(value = "order-search", allEntries = true),
            @CacheEvict(value = "order-status", allEntries = true)
    })
    public boolean invalidateOrderByIds(Long[] ids) {
        List<WxzOrder> wxzOrderList = Arrays.stream(ids)
                .map(id -> WxzOrder.builder()
                        .id(id)
                        .status(OrderStatus.CANCELLED.getCode())
                        .build())
                .collect(Collectors.toList());
        return updateBatchById(wxzOrderList);
    }

    /**
     * 清空表数据（重置学期）
     *
     * @return 是否操作成功
     */
    @Override
    @CacheEvict(value = {
            "operate-order",
            "in-progress",
            "order-statistics",
            "order-search",
            "order-status",
            "staff-ranking"
    }, allEntries = true)
    public boolean resetSemester() {
        orderMapper.truncateTable();
        return true;
    }
}